import { isEqual } from "lodash";

// 地图打点
export class MapMarker {
  currentCheckId = null;
  markerArr = [];
  cluster = null;
  checkedClusterLgt = null;
  infoWindow = null;
  allCarData = [];
  currentLabel = "carNum";
  onShowCarDetails = null;
  toolBar = null;
  sate = null;
  traffic = null;
  scale = null;
  ruler = null;
  show3D = true;
  showTraffic = false;
  showTraffic = false;
  showScale = true;
  showZoom = true;
  mapType = 0;
  currentZoomLevel = 5;
  callBackFunc = null;

  constructor(map) {
		this.map = map;
	}

  _createMarker(markerObj) {
    let [title, tooltipText] = this._handleTitle(markerObj.alias, markerObj.carNum, 7);
    const { carNum, rtOnline, lgt, lat } = markerObj;
		let marker = new AMap.Marker({
			position: new AMap.LngLat(markerObj.lgt, markerObj.lat), // 经纬度对象，也可以是经纬度构成的一维数组[116.39, 39.9],
			topWhenClick: true,
			extData: {
				lnglat: [lgt, lat],
				id: carNum,
				rtOnline,
				tooltipText,
				title
			}
		});
		this._setContentLabel(marker, title, tooltipText, rtOnline, carNum);
		// 定时更新数据时，当前选中marker超出视野范围内，从新定位marker
		carNum === this.currentCheckId &&
			(this.map.setCenter([markerObj.lgt, markerObj.lat]), marker.setTop(true));
		return marker;
  }

  // 更新marker
  updateMarker() {
    this.markerArr.forEach((v) => {
      const { title, rtOnline, id, tooltipText } = v?.getExtData();
      this._setContentLabel(v, title, tooltipText, rtOnline, id);
    });
  }

  renderMarker({ allCarData, clusterSwitch, showDetailsFun, callBackFunc}) {
    let marker;
    this.onShowCarDetails = showDetailsFun;
    this.callBackFunc = callBackFunc;
    this.allCarData = allCarData;
    this.allCarData?.forEach((o) => {
      o["lat"] = o.rtLatitude || "";
      o["lgt"] = o.rtLongitude || "";
      // 对每个market设置样式
      marker = this._createMarker(o);
      // marker添加点击事件
      this._onBindMarkerClick(o, marker);
      // marker添加移入事件
      this._onBindMarkerMouseover(o, marker);
      // marker移出事件
      this._onBindMarkerMouseout(o, marker);
      this.markerArr.push(marker);
    });
    // 添加cluster或者marker
    if (clusterSwitch) {
      // 初始化cluster
      this.initClusterMarker();
      return;
    }
    this.map.add(this.markerArr);
  }

  // marker 点击事件
  _onBindMarkerClick(o, marker) {
    marker.on("click", () => {
      this.onHandleClick(o, "markerClick");
    });
  }

  // marker点击事件处理
  onHandleClick(o, type) {
    this.handleClick(o, type);
    // 判断车辆详情展示交互
    this.onShowCarDetails(o);
  }

  // marker 移入事件
  _onBindMarkerMouseover(o, marker) {
    marker.on("mouseover", (e) => {
      if (!e.originEvent.target.classList.contains("arrow-right")) {
        return;
      }
      const content = [
        "<div class='car-menu-list' onclick='onClickMenu(event)'>",
        "<div class='car-menu-item'>详情</div>",
        "<div class='car-menu-item'>轨迹</div>",
        "<div class='car-menu-item'>视频</div>",
        "</div>"
      ];
      this.infoWindow = new AMap.InfoWindow({
        anchor: "top-left",
        offset: new AMap.Pixel(65, -60),
        content: content.join("") //使用默认信息窗体框样式，显示信息内容
      });
      this.infoWindow.open(this.map, marker.getPosition());
      window.onClickMenu = (e) => {
        let dom = e.target;
        let no = o.carNum;
        let divs = document.querySelectorAll(".car-menu-item");
        divs.forEach((o) => o.classList.remove("checked-current-car"));
        dom.classList.add("checked-current-car");
        if (dom.innerText === "轨迹") {
          let params = {
            carNum: no
          };
          this.callBackFunc(params);
        }
      };
    });
  }

  // marker 移出事件
  _onBindMarkerMouseout(o, marker) {
    marker.on("mouseout", () => {
      this.infoWindow && this.closeInfoWindow();
    });
  }

  // 清空聚合、打点数据
  clearMapDot() {
    if (this.cluster) {
      this.cluster.clearMarkers();
    }
    this.map.remove(this.markerArr);
    this.markerArr = [];
  }

  initClusterMarker() {
    this.cluster = new AMap.MarkerClusterer(this.map, this.markerArr, {
      gridSize: 80,
      maxZoom: 17,
      zoomOnClick: false,
      renderClusterMarker: this._renderClusterMarker
    });
    // 1、聚合点点击事件 2、鼠标滚轮滑动 3、鼠标滑动
    this._onClusterClick();
    this._onMousewheel();
    this._onMousemove();
  }

  // cluster鼠标移入事件
  _onMousemove() {
    this.cluster.on("mousemove", (val) => {
      console.log(val.target);
    });
  }

  // cluster鼠标滑块滚动事件
  _onMousewheel() {
    this.map.on("mousewheel", () => {
      if (this.infoWindow?.getIsOpen()) {
        this.closeInfoWindow();
      }
    });
  }

  // cluster点击事件打开信息窗口
  _onClusterClick() {
    this.cluster.on("click", (val) => {
      const isCheckedCluster = isEqual(val.lnglat, this.checkedClusterLgt);
      const isInfoOpen = this.infoWindow?.getIsOpen();
      if (isCheckedCluster && isInfoOpen) {
        this.closeInfoWindow();
        return;
      }
      const {
        lnglat: { lat, lng },
        markers
      } = val;
      const lnglat = [lng, lat];
      this.checkedClusterLgt = val.lnglat;
      const arr = markers?.map((o) => {
        const { id } = o.getExtData();
        return `<li data-id="${id}" class="${
          id === this.currentCheckId && "car-list-actived"
        }" >${id}</li>`;
      });
      const len = markers.length;
      const content = [
        "<ul class='common-scroll'>",
        ...arr,
        "</ul>",
        `<div class="open-markers" id="expand">展开</div>`
      ];
      // TODO infoWindow获取dom事件有问题, 此处换为SimpleInfoWindow, 后续优化
      AMapUI.loadUI(["overlay/SimpleInfoWindow"], (SimpleInfoWindow) => {
        this.infoWindow = new SimpleInfoWindow({
          anchor: "top-left",
          infoTitle: `<div class="vehicle-num">该区域内有${len}辆车</div>`,
          infoBody: content.join(""),
          closeWhenClickMap: true,
          offset: new AMap.Pixel(30, -30)
        });
        // 打开信息窗体
        this.infoWindow.open(this.map, lnglat);
        // 展开按钮绑定点击事件
        this._onBindExpand(lnglat);
        // 车辆列表绑定点击事件
        this._onBindCarList();
      });
    });
  }

  // 为展开按钮绑定点击事件
  _onBindExpand(lnglat) {
    this.infoWindow.get$InfoBody().on("click", "#expand", () => {
      this.closeInfoWindow();
      this.map.setCenter(lnglat);
      this.map.zoomIn();
    });
  }

  // 车辆弹窗列表点击事件
  _onBindCarList() {
    this.infoWindow.get$InfoBody().on("click", "li", (e) => {
      const { id } = e.target.dataset;
      const item = this.allCarData.find((o) => o.carNum === id);
      this.handleClick(item, "cardClick");
      this.onShowCarDetails && this.onShowCarDetails(item);
      this.closeInfoWindow();
    });
  }

  // 关闭信息窗
  closeInfoWindow() {
    this.infoWindow.close();
  }

  // marker点击事件处理
  handleClick(o, type) {
    // 当触发事见类型为 card点击时marker定位并缩放到最小
    // type: 1、markerClick 2、cardClick
    this._setZoomEvent(o, type);

    // 设置当前marker是否置顶
    this._setMarkerTop(o);
  }
  
  // 设置当前marker是否置顶
  _setMarkerTop(o) {
    this.markerArr.forEach((v) =>
      v.setTop(v.getExtData().id === o.carNum)
    );
  }

  // 当前点击事件为设置marker显示层级
  _setZoomEvent(o, type) {
    if (!o.lgt || !o.lat) return;
    var position = [o.lgt, o.lat];
    type === "cardClick"
      ? (this.map.setZoomAndCenter(18, position), this._setCurrentNodeZoom(18))
      : this.map.setCenter(position);
  }

  // 自定义聚合样式
  _renderClusterMarker(context) {
    const div = document.createElement("div");
    div.innerHTML = context.count;
    Object.assign(div.style, {
      backgroundColor: "#3D6CF7",
      width: "36px",
      height: "36px",
      border: "2px solid #fff",
      borderRadius: "50%",
      boxShadow: "1px 1px 4px 1px rgba(0,0,0,0.3)",
      color: "#fff",
      lineHeight: "32px",
      fontSize: "14px",
      textAlign: "center"
    });
    context.marker.setContent(div);
  }

  // 为marker设置content、label
  _setContentLabel(marker, title, tooltipText, rtOnline, id) {
    let flag = rtOnline === 1;
    let markerLabelType = flag ? "online-label" : "offline-label";
    let markerType = flag ? "online-marker" : "offline-marker";
    let content = `<span class="${markerLabelType} ${
      id === this.currentCheckId && "activeMarker"
    }"></span>`;
    let labelCon = `<span title="${tooltipText}" class="${markerType} ${
      id === this.currentCheckId && "activeLabelMarker"
    }">${title}</span><div class="arrow-right ${
      id !== this.currentCheckId && "hiddenArrow"
    }"></div>`;

    marker.setContent(content);
    marker.setLabel({
      direction: "top",
      content: labelCon
    });
  }

  // 别名处理
  _handleTitle(alias, carNum, num) {
    let text = alias
      ? alias.length > num
        ? alias.slice(0, num) + "..."
        : alias
      : "";
    let aliasText = alias ? alias : "";
    let title, tooltipText;
    switch (this.currentLabel) {
      case "total":
        title = `${carNum} ${text}`;
        tooltipText = `${carNum} ${aliasText}`;
        break;
      case "carNum":
        title = `${carNum}`;
        tooltipText = `${carNum}`;
        break;
      case "alias":
        title = `${text}`;
        tooltipText = `${aliasText}`;
        break;
    }
    return [title, tooltipText];
  }

  // 创建工具
  createTool() {
    this.sate = new AMap.TileLayer.Satellite();
    this.traffic = new AMap.TileLayer.Traffic();
    this.ruler = new AMap.RangingTool(this.map);
    this.scale = new AMap.Scale();
    this.toolBar = new AMap.ToolBar({
      liteStyle: true
    });
  }

  // 设置3d模式
  handle3D() {
    let pitch = this.show3D ? 35 : 0;
    this.map.setStatus({
      pitchEnable: true
    });
    this.map.setPitch(pitch);
    this.map.setStatus({
      pitchEnable: false
    });
  }

  // 设置卫星视图
  handlerLayer() {
    this.mapType ? this.map.add(this.sate) : this.map.remove(this.sate);
  }
  
  // 设置路况信息
  handlerTraffic() {
    this.showTraffic
      ? this.map.add(this.traffic)
      : this.map.remove(this.traffic);
  }

  // 设置比例尺
  handleScale() {
    this.showScale
      ? this.map.addControl(this.scale)
      : this.map.removeControl(this.scale);
  }

  // 设置缩放级别
  handleZoom() {
    this.currentZoomLevel = this.map.getZoom();
    let textNode = document.createTextNode(this.currentZoomLevel);
    let divDom = document.createElement("div");
    divDom.setAttribute("class", "zoom-level-type");
    divDom.appendChild(textNode);
    if (this.showZoom) {
      this.map.on("zoomchange", () => {
        this.onBindZoomChanged()
      });
      this.map.addControl(this.toolBar);
      let dom = document.querySelector(".amap-zoomcontrol");
      dom?.insertBefore(divDom, dom.childNodes[0]);
    } else {
      this.map.off("zoomchange", () => {
        this.onBindZoomChanged()
      });
      let dom = document.querySelector(".amap-zoomcontrol");
      dom?.removeChild(dom.childNodes[0]);
      this.map.removeControl(this.toolBar);
    }
  }

  // 为缩放工具栏绑定缩放事件
  onBindZoomChanged() {
    this._setCurrentNodeZoom();
    this.infoWindow && this.closeInfoWindow();
  }

  // 设置当前缩放工具栏缩放等级
  _setCurrentNodeZoom(zoom) {
    if (this.showZoom) {
      this.currentZoomLevel = zoom || this.map.getZoom();
      let levelDom =
        document.querySelector(".amap-zoomcontrol")?.firstElementChild;
      levelDom.innerHTML = this.currentZoomLevel;
    }
  }

  // 测距
  onRanging(flag) {
    flag ? this.ruler.turnOn() : this.ruler.turnOff();
  }
}

// 轨迹
export class AmapTrace {
  currentSpeed = 1000; //移动速度，后面调整速度已这个为基准
  movingCallback = null;
  markerIcon = null;
  pathSimplifierIns = null;
  paths = [];
  multiPaths = [];
  navg = null;
  totalDistance = 0;
  trackPlaybackInfos = [];
  customContentMap = null; // 回放车辆样式
  lineWidth = 5;
  strokeLineColor = "rgba(61, 108, 247, 0.6)";
  startImg = null;
  endImg = null;
  isMulti = false;
  movedDistance = 0;

  constructor(map) {
    this.map = map;
  }

  // 初始化轨迹数据
  initTrace(options) {
    this.markerIcon = options.markerIcon;
    this.startImg = options.startImg;
    this.endImg = options.endImg;
    this.isMulti = options.isMulti;
    this.currentSpeed = options.speed || 1000;
    
    this._onHandlePaths(options);
    this._initPathSimplifier()
    this._startEndMark();
  }

  //处理轨迹数据
  _onHandlePaths(options) {
    this.paths = this.isMulti ?
      this._formatMultiPath(options.routePath) :
      this._formatPath(options.routePath || []);
    this.totalDistance = this._handleDistance();
  }

  // 调用巡航器
  _initPathSimplifier() {
    this.pathSimplifierIns ? this._setPathData() : this._loadPathSimplifier();
  }

  // 加载巡航器实例
  _loadPathSimplifier() {
    AMapUI.load(
      [
        "ui/misc/PathSimplifier",
        "ui/overlay/SimpleMarker",
        "ui/misc/PointSimplifier",
        "lib/$"
      ],
      (PathSimplifier, SimpleMarker, PointSimplifier) => {
        // 轨迹显示
        if (!PathSimplifier.supportCanvas) {
          alert("当前环境不支持 Canvas！");
          return;
        }
        this.customContentMap = PathSimplifier.Render.Canvas.getImageContent(
          this.markerIcon,
          function onload() {
          },
          function onerror(e) {
            alert(e, "图片加载失败！");
          }
        );

        this.pathSimplifierIns = new PathSimplifier({
          zIndex: 100,
          map: this.map, //所属的地图实例
          clickToSelectPath: false,
          getPath: function (pathData) {
            return pathData.path;
          },
          getHoverTitle: function () {
            return null;
          },
          renderOptions: {
            renderAllPointsIfNumberBelow: -1, //绘制路线节点，如不需要可设置为-1
            pathLineHoverStyle: {
              lineWidth: 0,
              strokeStyle: "transparent",
              borderWidth: 0,
              borderStyle: "transparent",
              dirArrowStyle: false
            },
            //轨迹线的样式
            pathLineStyle: {
              strokeStyle: "#C5C5C5",
              lineWidth: this.lineWidth,
              borderStyle: "#ccc",
              borderWidth: 2
            },
            startPointStyle: {}, // 起始点
            endPointStyle: {}, // 终点
            pathNavigatorStyle: {
              content: PointSimplifier.Render.Canvas.getImageContent(
                this.markerIcon,
                function onload() { },
                function onerror() {
                  alert("图片加载失败！");
                }
              ),
              width: 22,
              height: 22,
              strokeStyle: "#ffffff",
              lineWidth: 1,
              zIndex: 300,
              pathLinePassedStyle: {
                strokeStyle: this.strokeLineColor,
                lineWidth: this.lineWidth,
                borderStyle: "#3D6CF7",
                borderWidth: 2
              }
            }
          }
        });
        this._setPathData();
      }
    );
  }

  //设置轨迹展示 轨迹线的数据
  _setPathData() {
    let pathData = this.isMulti ? this.paths : [
      {
        name: "轨迹",
        path: this.paths
      }
    ]
    this.pathSimplifierIns && (this.pathSimplifierIns.setData(pathData))
    this._createPathNavigator();
  }

  // 创建一个巡航器
  _createPathNavigator() {
    if (!this.navg && this.pathSimplifierIns) {
      this.navg = this.pathSimplifierIns.createPathNavigator(0, {
        loop: false, //循环播放
        speed: this.currentSpeed //巡航速度，单位千米/小时
      });
    }
  }

  // 计算总里程
  _handleDistance() {
    let distance = this.paths && AMap.GeometryUtil.distanceOfLine(this.paths);
    return distance;
  }

  // pathSource是路径点的集合， 路径点支持对象{lng, lat}和数组[lng, lat]
  _formatPath(pathSource) {
    return pathSource.map((o) => o.lng ? [o.lng, o.lat] : o);
  }

  // 处理批量数据
  _formatMultiPath(pathSource) {
    return pathSource;
  }

  // 计算移动距离
  triggerStepMove(target) {
    this.movedDistance = target.getMovedDistance();
  }

  // 更新速度
  updateSpeed(val) {
    const speed = +val * this.currentSpeed;
    this.navg?.setSpeed(speed);
  }

  // 停止动画
  stopAnimation() {
    if (this.navg) {
      this.navg.stop();
      this.navg.moveToPoint(0, 0);
    }
  }

  // 重置
  onResume() {
    this.navg.resume();
  }

  // 开始
  onStart() {
    this.navg.start();
  }

  // 暂停
  onPause() {
    this.navg.pause();
  }

  // 显示图标
  displayIcon(val) {
    console.log(val)
    if (!this.pathSimplifierIns) return;
    let options = this.pathSimplifierIns.getRenderOptions();
    options.pathNavigatorStyle.content = val
      ? this.customContentMap
      : "circle";
    options.pathNavigatorStyle.fillStyle = val ? null : "#3D6CF7";
    this.pathSimplifierIns.renderLater();
  }

  // 修改线路颜色
  changeColor(val) {
    this.strokeLineColor = val;
    let options = this.pathSimplifierIns.getRenderOptions();
    options.pathNavigatorStyle.pathLinePassedStyle.borderStyle = val;
    options.pathNavigatorStyle.pathLinePassedStyle.strokeStyle = val;
    this.pathSimplifierIns.renderLater();
  }

  // 修改线路宽度
  updateLineWidth(val) {
    this.lineWidth = val;
    this._renderOptions(val);
  }

  _renderOptions(val) {
    if (!this.pathSimplifierIns) return;
    let options = this.pathSimplifierIns.getRenderOptions();
    options.pathNavigatorStyle.pathLinePassedStyle.lineWidth = val;
    options.pathLineStyle.lineWidth = val;
    this.pathSimplifierIns.renderLater();
  }

  // 起始终点图标
  _startEndMark() {
    let markPoint = [
      this.paths[0],
      this.paths[this.paths.length - 1]
    ];

    for (let index = 0; index < 2; index++) {
      let Icon = new AMap.Icon({
        size: new AMap.Size(34, 38),
        image: index === 0 ? this.startImg : this.endImg,
        imageSize: new AMap.Size(34, 38)
      });
      let point = new AMap.Marker({
        icon: Icon,
        offset: new AMap.Pixel(-17, -38),
        position: markPoint[index]
      });
      this.map.add([point]);
    }
  }
}

// 实时轨迹
export class AmapRealTimeTrace {
  markerIcon = null;
  marker = null;
  polyline = null;
  paths = [];
  carNum = "";
  lineStyle = {};
  socket = {}

  constructor(mapInstance) {
    this.map = mapInstance;
  }

  initRealTimeTrack(options) {
    this.markerIcon = options.markerIcon;
    this.lineStyle = options.lineStyle;
    this._initSocket(options)
  }

  // 开启websocket
  _initSocket({ wsUrl, wsToken, wsParams }) {
    this.socket = new WebSocket(wsUrl, [
      encodeURIComponent(wsToken)
    ]);
    this.socket.onopen = () => {
      let obj = JSON.stringify(wsParams);
      this.socket.send(obj);
    };

    this.socket.addEventListener("message", (event) => {
      const { data } = event;
      if (data !== 'SUCCESS' && !!data) {
        let msg = JSON.parse(data);
        const  [{ vin, data: carData }] =  msg.data.data;
        this.carNum = vin;
        this.paths.push([carData.longitude, carData.latitude])
        this._initMarker()
        this._initPolyline();
      }
    });
  }

  // 关闭socket
  closeSocket() {
    this.socket.close();
  }

  // 初始化小车
  _initMarker() {
    this.map.clearMap();
    let pos = this.paths.length > 0 && this.paths[this.paths.length - 1]
    this.marker = new AMap.Marker({
      map: this.map,
      position: pos,
      offset: new AMap.Pixel(-5, -28),
      autoRotation: true
    });

    this._setContentLabel()
  }

  // 设置marker内容
  _setContentLabel() {
    let content = `<span class="online-label"></span>`;
    let labelCon = `<span class="online-marker">${this.carNum}</span>`;

    this.marker.setContent(content);
    this.marker.setLabel({
      direction: "top",
      content: labelCon
    });
  }

  // 画线
  _initPolyline() {
    let path = JSON.parse(JSON.stringify(this.paths))
    this.polyline = new AMap.Polyline({
      path,
      strokeWeight: 2,
      borderWeight: 2,
      strokeColor: 'red', // 线条颜色
      lineJoin: 'round', // 折线拐点连接处样式
      ...this.lineStyle
   });
   this.polyline.setMap(this.map)
   this.map.setFitView();
  }
}

// 电子围栏
export class AmapFence {
  mouseTool = null; //鼠标工具实例
  overlays = [];  //图层容器
  drawType = null;  // 绘制类型
  graphEditor = null; // 图形编辑态实例
  rectangleObj = null; // 矩形对象
  fenceGraph = null; // 图形对象
  graphStyle = {
    borderWeight: 2,
    strokeColor: "#3D6CF7",
    fillOpacity: 0.2,
    fillColor: "rgb(61,108,247)"
  };
  poiObj = {
    address: "",
    showResult: false,
    id: "tinId",
    placeholder: "请输入地址",
    result: [],
    count: 0,
    index: null,
    currentPage: 1
  };
  fenceForm = {};
  placeSearch = "";
  poiVal = "";
  showInfoModal = false;
  showMarker = true;
  marker = null;
  visible = false;
  modelValue = "";
  fenceInformation = [];
  INFORMATION_LIST = [];

  constructor(instance) {
    this.map = instance;
  }

  // 初始围栏数据
  initFence(options) {
    this.fenceForm = options?.fenceForm ?? {};
    this.graphStyle = options?.graphStyle ?? this.graphStyle;
    this.INFORMATION_LIST = options.informationList;
    this.mouseTool = new AMap.MouseTool(this.map);
    
    //监听draw事件可获取画好的覆盖物
    this._drawListener();
    // 地图点击poi搜索交互
    this.poiClickListener();
  }

  // 地图点击poi搜索交互
  poiClickListener() {
    this.map.on("click", () => {
      this.poiObj.showResult = false;
    });
    this.map.on("mouseup", () => {
      this.poiObj.showResult = false;
    });
  }

  // draw事件监听
  _drawListener() {
    //监听draw事件可获取画好的覆盖物
    this.mouseTool.on("draw", (e) => {
      this.mouseTool.close(false);
      this.overlays.push(e.obj);
      if (e.obj.CLASS_NAME === "AMap.Circle") {
        e.obj.setRadius(Math.round(e.obj.getRadius()));
      } else {
        if (e.obj.getPath().length > 30) {
          this.$message.error("节点数量不可大于30");
        }
      }
      // 启动编辑态;
      this.onEditor(e.obj, false);
    });
  }

  // 绘制
  onDraw(type) {
    this.overlays = [];
    this.drawType = type;
    this.map && this.map.clearMap();

    switch (type) {
      case 3: {
        this.mouseTool.polygon(this.graphStyle);
        break;
      }
      case 2: {
        this.mouseTool.rectangle(this.graphStyle);
        break;
      }
      case 1: {
        this.mouseTool.circle(this.graphStyle);
        break;
      }
    }
  }

  // 绘制多边形，单独处理
  _drawReactangle(obj) {
    const northEast = this.getAzimuth(obj, "northeast");
    const southWest = this.getAzimuth(obj, "southwest");
    const mybounds = new AMap.Bounds(southWest, northEast);

    this.rectangleObj = new AMap.Rectangle({
      bounds: mybounds,
      draggable: true,
      cursor: "pointer",
      ...this.graphStyle
    });
  }

  // 获取端点经纬度
  getAzimuth(graphObj, aspect) {
    return [
      graphObj.getBounds()[aspect].lng,
      graphObj.getBounds()[aspect].lat
    ];
  }

  // 围栏编辑 obj： 图形对象 bool： 添加区域或编辑区域
  onEditor(obj, bool) {
    this.poiObj.showResult && (this.poiObj.showResult = false);
    if (!bool) {
      const northEast = this.getAzimuth(obj, "northeast");
      const southWest = this.getAzimuth(obj, "southwest");
      const mybounds = new AMap.Bounds(southWest, northEast);
      let o1 = { bounds: mybounds, draggable: true, cursor: "pointer" };
      let options = Object.assign(o1, this.graphStyle);
      this.rectangleObj = new AMap.Rectangle(options);
      this._drawReactangle(obj);
    }
    switch (this.drawType) {
      case 3:
        this.graphEditor = new AMap.PolyEditor(this.map, obj);
        break;
      case 2:
        if (!bool) {
          this.map.add(this.rectangleObj);
          this.map.remove(this.overlays);
        }
        this.graphEditor = new AMap.RectangleEditor(
          this.map,
          bool ? obj : this.rectangleObj
        );
        break;
      case 1:
        this.graphEditor = new AMap.CircleEditor(this.map, obj);
        this.fenceGraph = obj;

        break;
    }
    this.graphEditor.open();
    // 开启监听事件
    this._onEventListener();
  }

  // 监听graphEditor编辑器
  _onEventListener() {
    this.graphEditor.on("addnode", (event) => {
      const target = event.target;
      if (target.getPath().length > 30) {
        this.$message.error("节点数量不可大于30");
        return;
      }
    });
    this.graphEditor.on("adjust", (event) => {
      let target = event.target;
      this.poiObj.showResult = false;
      this.overlays = [];
      this.overlays.push(target);
      if (target.CLASS_NAME === "AMap.Circle") {
        this.fenceForm.radius = target.getRadius();
      }
    });
    this.graphEditor.on("move", ({ target }) => {
      this.poiObj.showResult = false;
      if (target.CLASS_NAME === "AMap.Circle") {
        let center = [
          { x: target.getCenter().lng, y: target.getCenter().lat }
        ];
        this.fenceForm.coordinates = center;
      }
    });
    this._setRadius();
  }

  // 点击半径圆形半径设置
  _setRadius() {
    this.map.on("click", (e) => {
      let labeDom = e.originEvent.target;
      let isMarkerLabel = labeDom.classList.contains("amap-marker-label");
      let isSiblingDom =
        labeDom.previousElementSibling.title === "拖拽修改半径";
      if (isMarkerLabel && isSiblingDom && this.fenceGraph) {
        let radius = this.fenceGraph.getRadius();

        this.overlays.push(this.fenceGraph);
        this._setInfoWindow(radius);
      }
    });
  }

  // 绘制图形
  drawGraph(data, type, clickGraphFunc) {
    if (!data) return;
    this.overlays = [];
    if (data.coordinates && data.coordinates.length) {
      let pathArray = data.coordinates;
      let path = pathArray?.map((item) => {
        return new AMap.LngLat(item.x, item.y);
      });
      switch (data.shape) {
        case 3: {
          let o1 = { path: path.slice(0, -1), extData: data };
          let options = Object.assign(o1, this.graphStyle);
          this.fenceGraph = new AMap.Polygon(options);
          break;
        }
        case 2: {
          var bounds = new AMap.Bounds(data.southWest, data.northEast);
          let o1 = { bounds: bounds, extData: data };
          let options = Object.assign(o1, this.graphStyle);
          this.fenceGraph = new AMap.Rectangle(options);
          break;
        }
        case 1: {
          let o1 = {
            center: path[0],
            radius: Number(data.radius),
            extData: data,
            bubble: true
          };
          let options = Object.assign(o1, this.graphStyle);
          this.fenceGraph = new AMap.Circle(options);
          break;
        }
      }
      this.overlays.push(this.fenceGraph);
      clickGraphFunc();
      this.map.add(this.fenceGraph);
      if (type !== "cancel") this.map.setFitView([this.fenceGraph], true);
    }
  }

  // 判断两个线段是否相交
  doesSegmentsIntersect(graphObj) {
    let arr = [];
    let paths = graphObj.getPath().map((o) => [o.lng, o.lat]);
    paths.forEach((o, i) => {
      let v = i === paths.length - 1 ? paths[0] : paths[i + 1];
      arr.push([o, v]);
    });
    let isIntersect = arr.some((o) => {
      return arr.some((v) => {
        if (!isEqual(o[0], v[1]) && !isEqual(o[1], v[0])) {
          return AMap.GeometryUtil.doesSegmentsIntersect(...o, ...v);
        }
      });
    });
    return isIntersect;
  }

  // 移除图形对象
  onRemove() {
    this.poiObj.showResult = false;
    this.drawType = "";
    // close鼠标绘制
    if (this.mouseTool) {
      this.mouseTool.close(false);
    }
    // 移除 添加区域矩形
    if (this.rectangleObj) {
      this.map.remove(this.rectangleObj);
      this.rectangleObj = null;
    }

    // 关闭编辑
    if (this.graphEditor) {
      this.graphEditor.close();
      this.graphEditor = null;
    }
  }

  // 区域图形对应参数
  doesSaveGraphParams(graphObj, coordinatesData) {
    if (graphObj.CLASS_NAME === "AMap.Circle") {
      let center = [
        {
          x: graphObj.getCenter().getLng(),
          y: graphObj.getCenter().getLat()
        }
      ];
      this.fenceForm.coordinates = center;
      this.fenceForm.radius = graphObj.getRadius();
    } else {
      let coordinates = coordinatesData.map((o) => {
        return { x: o.lng, y: o.lat };
      });
      coordinates.push(coordinates[0]); // 添加第一个形成闭环(接口要求)
      this.fenceForm.coordinates = coordinates;
      // 矩形
      if (this.fenceForm.shape === 2) {
        this.fenceForm.southWest = this.getAzimuth(
          graphObj,
          "southwest"
        );
        this.fenceForm.northEast = this.getAzimuth(
          graphObj,
          "northeast"
        );
      }
    }
  }

  // poi 关键字change
  poiChange(e) {
    if (this.map) {
      this.poiObj.index = null;
      this.poiObj.currentPage = 1;
      this.removeMarker();
      this.initPoi(e.target.value);
    }
  }
  // 地点搜索 poi关键字搜索
  initPoi(val) {
    this.poiVal = val;
    this.placeSearch = new AMap.PlaceSearch({
      pageSize: 10,
      pageIndex: this.poiObj.currentPage,
      autoFitView: true,
      renderStyle: "default"
    });
    //关键字查询
    this.placeSearch.search(val, (status, result) => {
      if (status === "complete") {
        this.poiObj.count = result.poiList.count;
        this.poiObj.result = result.poiList.pois;
        this.poiObj.showResult = true;
        this.poiObj.currentPage = result.poiList.pageIndex;
      } else {
        this.poiObj.result = [];
        if (!val) {
          this.poiObj.showResult = false;
        }
      }
    });
  }
  // poi 选择地点搜索结果
  selectPoiPanel(data) {
    this.showInfoModal = false;
    this.showMarker = true;
    if (this.marker) {
      let extData = this.marker.getExtData();
      if (data.data.id === extData.id) {
        this.poiObj.index = null;
        this.removeMarker();
      } else {
        this.removeMarker();
        this.poiObj.index = data.index;
        this.setMarker(data.data);
      }
    } else {
      this.poiObj.index = data.index;
      this.setMarker(data.data);
    }
  }
  // 地点搜索翻页 上一页、下一页
  changepage(type) {
    let pageIndex = this.poiObj.currentPage;
    if (type === "prev") {
      this.poiObj.currentPage = pageIndex === 1 ? 1 : pageIndex - 1;
    } else {
      this.poiObj.currentPage = pageIndex + 1;
    }
    this.placeSearch.setPageIndex(this.poiObj.currentPage);
    this.placeSearch.search(this.poiVal, (status, res) => {
      if (status === "complete") {
        this.poiObj.index = null;
        this.poiObj.result = res.poiList.pois;
        this.poiObj.currentPage = res.poiList.pageIndex;
      }
    });
  }
  // 地点搜索设置标记点
  setMarker(data) {
    this.marker = null;
    let lnglat = data.location;
    let locationIcon = new AMap.Icon({
      image: require(`@/assets/img/location.png`),
      imageSize: new AMap.Size(34, 38)
    });
    this.marker = new AMap.Marker({
      position: new AMap.LngLat(lnglat.R, lnglat.Q),
      title: data.name,
      icon: locationIcon,
      offset: new AMap.Pixel(-17, -32),
      label: {
        offset: new AMap.Pixel(0, -10),
        content: `<div class='info'>
        <span class='name'>${data.name}</span><div class='address'>${
          data.address || "暂无详细地址"
        }</div></div>`,
        direction: "top"
      },
      extData: data
    });
    this.marker.on("click", (e) => {
      this.showMarker = !this.showMarker;
      if (!this.showMarker) {
        e.target.setLabel({
          content: ""
        });
      } else {
        let target = e.target;
        const extra = target.getExtData();
        target.setLabel({
          offset: new AMap.Pixel(0, -10),
          content: `<div class='info'>
        <span class='name'>${extra.name}</span><div class='address'>${
            extra.address || "暂无详细地址"
          }</div></div>`,
          direction: "top"
        });
      }
    });
    this.map.add(this.marker);
    this.map.setFitView([this.marker]);
  }
  // 移除标记点
  removeMarker() {
    if (this.marker) {
      this.map.remove(this.marker);
      this.marker = null;
    }
  }

  // 设置半径输入框聚焦交互
  onFocus(e) {
    this.map.setStatus({ keyboardEnable: false });
    if (e.target.value) {
      this.poiObj.showResult = true;
      this.initPoi(e.target.value);
    } else {
      this.poiObj.currentPage = 1;
      this.poiObj.count = 0;
      this.poiObj.result = [];
      this.poiObj.showResult = false;
    }
  }

  // 设置半径输入框失去焦点交互
  onBlur() {
    this.map.setStatus({ keyboardEnable: true });
  }

  // 点击区域
  onClickGraph() {
    this.fenceGraph.on("click", (e) => {
      // 显示隐藏 围栏信息
      this.showInfoModal = !this.showInfoModal;
      this._handleInfomation(e.target.getExtData());
    });
  }

  // 围栏信息
  _handleInfomation(data) {
    let reduceArr = [];
    for (const iterator in this.INFORMATION_LIST) {
      reduceArr.push({
        key: this.INFORMATION_LIST[iterator],
        value: data[iterator]
      });
    }
    this.fenceInformation = reduceArr;
  }

  radiusSetInput(e) {
    let reg = /[^\d]/g,
      val = e.target.value;
    let n = val.search(reg);
    this.modelValue = n !== -1 ? val.slice(0, n) : val;
  }

  // 设置半径保存
  handleRadiusOk(data) {
    this.fenceForm.radius = data;
    this.fenceGraph.setRadius(data);
    this.visible = false;
    this.map.setFitView([this.fenceGraph], true);
  }

  // 半径设置change
  handleRadiusChange(e) {
    let value = e.target.value;
    this.modelValue = value;
    if (value.length > 7) {
      this.modelValue = value.slice(0, 7);
    }
  }

  // 取消设置半径
  handleRadiusCancel(data) {
    this.visible = data;
    this.overlays = [];
  }

  // 显示设置半径弹窗
  _setInfoWindow(radius) {
    this.visible = true;
    this.modelValue = radius;
  }
}

// 实时告警
export class AmapFenceWarn {
  socket = null;
  fenceCallback = null;

  constructor(options) {
    this._initRealTimeWarn(options)
  }

  // 初始化socket
  _initRealTimeWarn(options) {
    this.fenceCallback = options.fenceCallback;
    this._initSocket(options)
  }

  // 开启websocket
  _initSocket({ wsUrl, wsToken, wsParams }) {
    this.socket = new WebSocket(wsUrl, [
      encodeURIComponent(wsToken)
    ]);

    this.socket.onopen = () => {
      let obj = JSON.stringify(wsParams);
      this.socket.send(obj);
    };

    this.socket.addEventListener("message", (event) => {
      const { data } = event;
      if (data !== 'SUCCESS' && !!data) {
        let msg = JSON.parse(data);
        const  [{ data: warnData }] =  msg.data.data;
        this.fenceCallback(warnData)
      }
    });
  }

  // 关闭socket
  closeSocket() {
    this.socket.close();
  }
}
